/**
 * 
 */
package br.com.framework.negocio.api;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import javax.persistence.PersistenceException;

import br.com.framework.negocio.exception.NegocioException;
import br.com.framework.persistencia.api.BaseDao;
import br.com.framework.persistencia.model.BaseEntity;
import br.com.framework.persistencia.sort.Order;

/**
 * Interface de Negócio de uma entidade, que implementa operações básicas através 
 * do padrão Session Facade.
 * 
 * @author Cleber Moura
 *
 * @param <ID>
 * @param <E>
 */
public interface BaseNegocio<E extends BaseEntity, DAO extends BaseDao<E>> extends Serializable{
	
	/**
	 * Busca uma entidade pelo Id
	 * @param id
	 * @return
	 * @throws PersistenceException
	 */
	E findByID(Long id) throws PersistenceException;
	
	/**
	 * Busca todos os registros ativos.
	 * @return
	 * @throws PersistenceException
	 */
	List<E> findAll() throws PersistenceException;
	
	/**
	 * Busca todos os registros.
	 * 
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos; 
	 * @return
	 * @throws PersistenceException
	 */
	List<E> findAll(boolean onlyActive) throws PersistenceException;
	
	/**
	 * Busca todos os registros ativos de forma paginada.
	 * 
	 * @param firstResult
	 * @param maxResults
	 * @return
	 * @throws PersistenceException
	 */
	List<E> findAll(int firstResult, int maxResults) throws PersistenceException;
	
	/**
	 * Busca todos os registros de forma paginada.
	 * 
	 * @param firstResult
	 * @param maxResults
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findAll(int firstResult, int maxResults, boolean onlyActive) throws PersistenceException;
	
	/**
	 * Busca todos os registros de forma paginada e ordenada.
	 * 
	 * @param firstResult
	 * @param maxResults
	 * @param sortField
	 * @param sortOrder
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findAll(int firstResult, int maxResults, String sortField, Order sortOrder, boolean onlyActive) throws PersistenceException;
	
	/**
	 * Busca todos os registros de forma ordenada.
	 * 
	 * @param sortField
	 * @param sortOrder
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findAll(String sortField, Order sortOrder, boolean onlyActive) throws PersistenceException;
	
	/**
	 * Busca todos os registros de forma paginada, filtrada e ordenada.
	 * 
	 * @param firstResult
	 * @param maxResults
	 * @param sortField
	 * @param sortOrder
	 * @param filters
	 * 	Map<String, String> Representando a coluna e o valor para a filtragem.
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findAll(int firstResult, int maxResults, String sortField, Order sortOrder, Map<String, String> filters, boolean onlyActive) throws PersistenceException;
	
	/**
	 * Insere uma nova entidade.
	 * 
	 * @param entidade
	 * @return
	 * @throws PersistenceException
	 * @throws NegocioException
	 */
	void insert(E entidade) throws PersistenceException, NegocioException;
	
	/**
	 * Modifica os dados da entidade no banco de dados.
	 *  
	 * @param entidade
	 * @return
	 * @throws PersistenceException
	 * @throws NegocioException
	 */
	void update(E entidade) throws PersistenceException, NegocioException;
	
	/**
	 * Recarrega os dados da entidade do banco de dados. 
	 * 
	 * @param entidade
	 * @return
	 * @throws PersistenceException
	 */
	void refresh(E entidade) throws PersistenceException;
	
	/**
	 * Efetrua a remoção lógica de um registro.
	 * 
	 * @param entidade
	 * @throws PersistenceException
	 * @throws NegocioException
	 */
	void remove(E entidade) throws PersistenceException, NegocioException;
	
	/**
	 * Efetua a remoçao de um registro. 
	 * Se o parametro 'removerDefinitivamente' true, será feita a remoção definitiva do registro no banco de dados.
	 * 
	 * @param entidade
	 * @param removerDefinitivamente
	 * @throws PersistenceException
	 * @throws NegocioException
	 */
	void remove(E entidade, boolean removerDefinitivamente) throws PersistenceException, NegocioException;
	
	/**
	 * Efetrua a remoção lógica de um registro pelo ID.
	 * 
	 * @param id
	 * @throws PersistenceException
	 * @throws NegocioException
	 */
	void remove(Long id) throws PersistenceException, NegocioException;
	
	/**
	 * Efetua a remoçao de um registro pelo ID
	 * Se o parametro 'removerDefinitivamente' true, será feita a remoção definitiva do registro no banco de dados.
	 * 
	 * @param id
	 * @param removerDefinitivamente
	 * @throws PersistenceException
	 * @throws NegocioException
	 */
	void remove(Long id, boolean removerDefinitivamente) throws PersistenceException, NegocioException;
	
	/**
	 * Retorna o total de registros ativos.
	 * 
	 * @return
	 * @throws PersistenceException
	 */
	public Long getRecordCount() throws PersistenceException;
	
	/**
	 * Retorna o total de registros.
	 * 
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public Long getRecordCount(boolean onlyActive) throws PersistenceException;
	
	/**
	 * Retorna o total de registros.
	 * 
	 * @param filters
	 * 	Map<String, String> Representando atributo/valor para a filtragem.
	 * @param onlyActive
	 * 	true - o resultado conterá apenas os registros ativos; <br/>
	 *  false - o resultado conterá todos os registros, ativos e inativos;
	 * @return
	 * @throws PersistenceException
	 */
	public Long getRecordCount(Map<String, String> filters, boolean onlyActive) throws PersistenceException;
	
	/**
	 * Busca os registros atraves de uma entidade exemplo.
	 * Permite utilizar paginação.
	 * 
	 * @param entidade
	 * @param firstResult
	 * @param maxResults
	 * @param sortField
	 * 	Campo de ordenação do resultado.
	 * @param sortOrder
	 * 	Ordenação ASC, DESC
	 * @param isStringCaseSensitive
	 * 	true - as comparações de campos {@link String} serão case sensitive
	 *  false - as comparações de campos {@link String} serão realizadas em lower case.
	 * @param isLikeEnabled
	 * 	true - Na comparação de {@link String} será utilizado o operador LIKE.
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findByExample(E entidade, int firstResult, int maxResults,
			String sortField, Order sortOrder, boolean isStringCaseSensitive, boolean isLikeEnabled) throws PersistenceException;
	
	/**
	 * Busca os registros atraves de uma entidade exemplo.
	 * 
	 * @param entidade
	 * @param isStringCaseSensitive
	 * 	true - as comparações de campos {@link String} serão case sensitive
	 *  false - as comparações de campos {@link String} serão realizadas em lower case.
	 * @param isLikeEnabled
	 * 	true - Na comparação de {@link String} será utilizado o operador LIKE.
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findByExample(E entidade, boolean isStringCaseSensitive, boolean isLikeEnabled) throws PersistenceException;
	
	/**
	 * Busca os registros atraves de uma entidade exemplo.
	 * Permite ordenar o resultado.
	 * 
	 * @param entidade
	 * @param sortField
	 * 	Campo de ordenação do resultado.
	 * @param sortOrder
	 * 	Ordenação ASC, DESC
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findByExample(E entidade, String sortField, Order sortOrder) throws PersistenceException;
	
	/**
	 * Busca os registros atraves de uma entidade exemplo.
	 * Por padrão as comparações de {@link String} são case sensitive e não utiliza operador like.
	 * A ordenação padrão é ASC.
	 * 
	 * @param entidade
	 * @return
	 * @throws PersistenceException
	 */
	public List<E> findByExample(E entidade) throws PersistenceException;
	
}
